package com.kuaihuoyun.toolkit.code2pdf;

import com.google.common.collect.Lists;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.List;
import java.util.stream.Stream;

/**
 * Created by lxji on 2017/3/2.
 */
public class CodeToPdfWriter {
    private static final Logger log = LoggerFactory.getLogger(CodeToPdfWriter.class);

    public CodeToPdfWriter() {

    }

    public void write(File codePath, File outPath, ProgressListener progressListener) throws FileNotFoundException, DocumentException {
        log.debug("start .....");

        if (!codePath.exists()) {
            throw new FileNotFoundException("code path not found, " + codePath.getAbsolutePath());
        }

        if (codePath.isDirectory()) {
            List<File> files = Lists.newArrayList();
            listAllFilesInDirectory(codePath, files);

            Document doc = new Document();
            File outFile = new File(outPath.getAbsolutePath() + "/" + codePath.getName() + ".pdf");
            PdfWriter.getInstance(doc, new FileOutputStream(outFile));
            doc.open();

            progressListener.onUpdate(0);

            int count = 0;
            int total = files.size();
            String rootPath = codePath.getAbsolutePath();
            for (File file : files) {
                writeFileToPdf(file, rootPath, doc);
                count ++;

                progressListener.onUpdate((int)Math.round(100.0 * count / total));
            }
            doc.close();

            progressListener.onComplete();
        }
    }

    private static void listAllFilesInDirectory(File directory, List<File> files) {
        File[] filesInDirectory = directory.listFiles(pathname -> {
            String fileName = pathname.getName();
            if (pathname.isDirectory()) {
                if (fileName.startsWith(".")) {
                    return false;
                }
            } else {
                if (!fileName.endsWith(".java")
                        && !fileName.endsWith(".h")
                        && !fileName.endsWith(".c")
                        && !fileName.endsWith(".hpp")
                        && !fileName.endsWith(".cpp")
                        && !fileName.endsWith(".cxx")
                        && !fileName.endsWith(".py")) {
                    return false;
                }
            }


            return true;
        });

        for (File file : filesInDirectory) {
            if (file.isFile()) {
                files.add(file);
            } else if (file.isDirectory()) {
                listAllFilesInDirectory(file, files);
            }
        }
    }

    private static void writeFileToPdf(File file, String rootPath, Document doc) throws FileNotFoundException, DocumentException {
        String fullPath = file.getAbsolutePath();
        log.info("writeFileToPDF:{}", fullPath);

        String filePath = fullPath.substring(rootPath.length());
        doc.add(new Paragraph(""));
        doc.add(new Paragraph("File:" + filePath));
        BufferedReader reader = new BufferedReader(new FileReader(file));
        Stream<String> stringStream = reader.lines();
        stringStream.forEach((line) -> {
            try {
                doc.add(new Paragraph(line));
            } catch (DocumentException e) {
                log.error("error:{}", e);
            }
        });

        doc.add(new Paragraph(""));
    }
}
